
package com.scalar.chiptrack.operations.process.actions;

import java.util.ArrayList;
import java.util.HashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.scalar.ScalarException;
import com.scalar.chiptrack.ChipTrackAction;
import com.scalar.chiptrack.commons.SessionKeys;
import com.scalar.chiptrack.db.DBTransaction;
import com.scalar.chiptrack.operations.process.BinSetup;
import com.scalar.chiptrack.operations.process.dao.BinSetupDAO;
import com.scalar.chiptrack.operations.process.dao.ProcessTrackDAO;
import com.scalar.chiptrack.users.User;


public class BinSetupAction extends ChipTrackAction {

    private ArrayList m_bins = null;
    private ArrayList m_goodBins = null;
    private ArrayList m_goodPartNumbers = null;
    private String[] m_partNumbers = null;
	private String[] m_oldPartNumbers = null;
    
    public ActionForward execute (ActionMapping mapping,
                              ActionForm form,
                              HttpServletRequest request,
                              HttpServletResponse response) 
                              throws Exception {
             
        DBTransaction dbTransaction = null;
        boolean success = false;
        HttpSession session = request.getSession();
        
		User user = (User)session.getAttribute (SessionKeys.USER_KEY);
		if (user == null)
		{
			return (mapping.findForward ("login"));
		}
        
        String action = request.getParameter ("action");
        HashMap errors = new HashMap();
        
        int processStepId = Integer.parseInt ((String) session.getAttribute ("processStepId"));
        int oldProcessStepId = Integer.parseInt ((String) session.getAttribute ("oldProcessStepId"));
        
        // SAVE ACTION
        if ("save".equalsIgnoreCase(action)) 
        {
            try 
            {
                // start transaction 
                dbTransaction = DBTransaction.getInstance();
                dbTransaction.begin();

                int trackId = Integer.parseInt ((String) session.getAttribute("trackId"));
				int baseProductId = Integer.parseInt ((String) session.getAttribute("baseProductId"));
                String stepName = (String) session.getAttribute ("stepName");

                // Get Bin Information from HTTP Request
                try 
                {
                    parseBinInfoFromRequest (request);
                    success = true;
                }
                catch (Exception e) 
                {
                    e.printStackTrace();
                    errors.put ("Invalid values", e.getMessage());
                    request.setAttribute (SessionKeys.ERROR_MESSAGES, errors);
                }

                // Step 1
                // Check for PartNumbers already existing for the newly entered Part Numbers
                 
				//String result = checkBinInfoInProduct();
				String result = checkBinInfo(processStepId);
				
				if( result.length() > 0 )
				{
					success = false;
					errors.put ("Part Numbers Already exists ", result );
					request.setAttribute (SessionKeys.ERROR_MESSAGES, errors);
				}
				
				if (success == false) 
				{
					ArrayList binList = getBinInformation(request);
					/*if (oldProcessStepId != -1) 
					{  
						binList = BinSetupDAO.loadBins (oldProcessStepId,trackId);
					}
					else 
					{
						binList = BinSetupDAO.loadBins (processStepId,trackId);
					}*/
					request.setAttribute ("binList", binList);  
					return (mapping.findForward ("failure"));
				}
				
                // Step 2
                // Save Bin information into database
                //int productIdSeed = (productId - (m_partNumbers.length-1));
                BinSetupDAO.saveBins (dbTransaction, processStepId, baseProductId, /*productIdSeed, */m_bins.iterator());

                // Step 3
                // Insert a new row in Mark_FG_Track_Table
                // commented on 27 Aug 2003 by ravikanth  
                // ProcessTrackDAO.saveGoodBinPartNumbers (dbTransaction, trackId, stepName, m_goodPartNumbers.iterator());
                
				ProcessTrackDAO.saveGoodBinPartNumbers (dbTransaction, trackId, stepName, m_goodBins );
				
				// Step 4
				// To update BinSubstitutables if the partnumber is changed
				for( int x=0 ; x < m_partNumbers.length ; x++ )
				{
					if( m_partNumbers[x] != null && m_partNumbers[x].length() > 0 && m_oldPartNumbers[x] != null && m_oldPartNumbers[x].length() > 1 )
					{
						if( !m_partNumbers[x].equals(m_oldPartNumbers[x]) )
						{
							BinSetupDAO.updateBinSubtitutables( dbTransaction, m_partNumbers[x] , m_oldPartNumbers[x] );						
						}
					}
				}

                // Step 5
                // Update TEST trackID information
                if ((m_goodBins != null) && (m_goodBins.size() <= 1)) 
                {
                    ProcessTrackDAO.updateTestTrack (dbTransaction, processStepId, trackId, stepName);
                }   
                else 
                {
                    // save it in session, bin_substitute page requires the bin information
                    request.getSession().setAttribute (SessionKeys.GOOD_BINS, m_goodBins);
                }
                // End transaction 
                success = true;
            }
            catch (ScalarException se) 
            {
                System.out.println ("Could not save bin information into database: " + se.getRootCause().getMessage());
                se.getRootCause().printStackTrace();
                
                errors.put ("Internal Server Error", "Could not save bin information into database");
                request.setAttribute (SessionKeys.ERROR_MESSAGES, errors);   
            }
            finally {
                // Rollback or Commit the Transaction
                if (success == true) {
                    dbTransaction.commit();
                }
                else {
                    dbTransaction.rollback();
                }
            }

            if (success == false) {
				ArrayList binList = getBinInformation(request);
				request.setAttribute ("binList", binList); 
                return (mapping.findForward ("failure"));
            }
            
            // if there are no possible Substitution, go to processView
            if ((m_goodBins != null) && (m_goodBins.size() <= 1)) {

                request.setAttribute("baseProductID", session.getAttribute ("baseProductId"));

                session.removeAttribute ("processStepId");
                session.removeAttribute ("trackId");
                session.removeAttribute ("stepName");
                session.removeAttribute ("baseProductId");

                return (mapping.findForward ("processView"));
            }
            request.setAttribute("formTestBin","true");
			return (mapping.findForward ("binSubstitutable"));
        }
        
        // VIEW ACTION
        try {
            ArrayList binList = null;
            if (oldProcessStepId != -1) {
                binList = BinSetupDAO.loadBins (oldProcessStepId);
            }
            else {
                binList = BinSetupDAO.loadBins (processStepId);
            }
            
            request.setAttribute ("binList", binList);
        }
        catch (ScalarException se) {
            System.out.println ("Exception while loading bin information: " + se.getRootCause());
        }
        
        return (mapping.findForward ("success"));
    }
    
    /**
	 * @param request
	 * @return
	 */
	private ArrayList getBinInformation(HttpServletRequest request) throws ScalarException
	{
		ArrayList binList = new ArrayList(10);
		int binCount = -1;
		String[] partNumbers = request.getParameterValues ("partNumber");
		String[] binDescription = request.getParameterValues ("binDescription");
		String[] yieldValues = request.getParameterValues ("yield");
		String[] binNumber = request.getParameterValues ("binNo");
		String[] markPackProcessStepID = request.getParameterValues("mark_Pack_ProcessStep_ID");
		String[] fGProcessStepID = request.getParameterValues("fG_ProcessStep_ID");
		String binType = null;
		BinSetup bin = null;
		float yield = 0.0f;
	
		try 
		{
			binCount = Integer.parseInt (request.getParameter("count")) - 1;
		}
		catch (NumberFormatException nfe) 
		{
			throw new ScalarException ("Could not get bin count");
		}
		
		for (int i=0; i<binCount; i++) 
		{
			try 
			{
				yield = Float.parseFloat (yieldValues[i]);
			}
			catch (NumberFormatException nfe) 
			{
				throw new ScalarException ("Invalid Yield Value - " + yieldValues[i]);
			}
			bin = new BinSetup (binNumber[i], request.getParameter ("binType"+(i)),binDescription[i], partNumbers[i],yield,markPackProcessStepID[i],fGProcessStepID[i]);
			bin.setOldPartNumber(m_oldPartNumbers[i]);
			binList.add(bin);										  
		}
		return binList;
	}

	private void parseBinInfoFromRequest (HttpServletRequest request) throws Exception {

        m_bins = new ArrayList();
        m_goodPartNumbers = new ArrayList();
        m_goodBins = new ArrayList();
        
        int binCount = -1;
        try 
        {
            binCount = Integer.parseInt (request.getParameter("count")) - 1;
        }
        catch (NumberFormatException nfe) 
        {
            throw new ScalarException ("Could not get bin count");
        }
        
        m_partNumbers = request.getParameterValues ("partNumber");
		m_oldPartNumbers = request.getParameterValues ("oldPartNumber"); 
		String[] binDescription = request.getParameterValues ("binDescription");
        String[] yieldValues = request.getParameterValues ("yield");
		String[] binNumber = request.getParameterValues ("binNo");
		String[] markPackProcessStepID = request.getParameterValues("mark_Pack_ProcessStep_ID");
		String[] fGProcessStepID = request.getParameterValues("fG_ProcessStep_ID");
        
        BinSetup bin = null;
        String binType = null;
        float yield = 0.0f;
        
		/*  commented by ravikanth on 27 Aug 2003
		 *  this has been commented as the parameters 
		 *  have been changed and some additional fields added
		 *      
       for (int i=0; i<binCount; i++) 
        {
            binNumber = "Bin" + (i+1);
            binType = request.getParameter ("binType"+(i+1));
            
            try 
            {
                yield = Float.parseFloat (yieldValues[i]);
            }
            catch (NumberFormatException nfe) 
            {
                throw new ScalarException ("Invalid Yield Value - " + yieldValues[i]);
            }
            
            if (yield > 100) throw new ScalarException ("Invalid yield value - " + yield);
            
            bin = new BinSetup (binNumber, binType, binDescription[i], m_partNumbers[i], yield);
            
            if (BinSetup.TYPE_ACCEPT.equalsIgnoreCase (binType) == true) 
            {
                m_goodPartNumbers.add (m_partNumbers[i]);
                m_goodBins.add (bin);
            }
            m_bins.add (bin);
            
        } */
        
		for (int i=0; i<binCount; i++) 
	    {
		   binType = request.getParameter ("binType"+(i));
		   try 
		   {
			   yield = Float.parseFloat (yieldValues[i]);
		   }
		   catch (NumberFormatException nfe) 
		   {
			   throw new ScalarException ("Invalid Yield Value - " + yieldValues[i]);
		   }
    
		   if (yield > 100) throw new ScalarException ("Invalid yield value - " + yield);
    
    	   
		   bin = new BinSetup (binNumber[i], binType, binDescription[i], m_partNumbers[i], yield, markPackProcessStepID[i], fGProcessStepID[i] );
     	   bin.setOldPartNumber( m_oldPartNumbers[i] );
     	   
		   if (BinSetup.TYPE_ACCEPT.equalsIgnoreCase (binType) == true) 
		   {
			   m_goodPartNumbers.add (m_partNumbers[i]);
			   m_goodBins.add (bin);
		   }
		   m_bins.add (bin);
    
	    }
    }
    
	/*
	 * to check the existance of the part number in WIP_STEP_BIN_TABLE and 
	 * for Board and Kits in Product table
	 */     
	private String checkBinInfo (int processStepId) throws ScalarException 
	{
		String str  = "'";
		String result = "";
				
		for(int i=0 ; i < m_bins.size() ; i++ )
		{
			BinSetup bin = (BinSetup)m_bins.get(i);
			if( bin.getPartNumber().trim().length() > 0 /*&& bin.getMark_Pack_ProcessStep_ID().equals("-1")*/)
			{
				str = str + bin.getPartNumber().trim()+"','";
			}
		 }
		 if( str.length() > 1 )
		 {
			result = BinSetupDAO.checkBins( str.substring(0,str.length()-2), processStepId );
		 }
		 
		 if( str.length() > 1 && result.length() == 0 )
		 {
			result = BinSetupDAO.checkBinsInProductForBoardKit( str.substring(0,str.length()-2));
		 }
		 
	/*	for(int i=0 ; i < m_bins.size() ; i++ )
		{
			BinSetup bin = (BinSetup)m_bins.get(i);
			if( bin.getPartNumber().trim().length() > 0 && !bin.getMark_Pack_ProcessStep_ID().equals("-1"))
			{
				str = BinSetupDAO.checkBinsByProcessId( processStepId , bin.getPartNumber().trim());
				if( str.length() > 0 )
				{
					result = result + "," + str ;
				}
			}
		}
	 */	
	 	return result;
	}
	
	
	//	to check the existance of the product name Product table
	
	private String checkBinInfoInProduct () throws ScalarException 
	{
		String str  = "'";
		String result = "";
				
		// this is to check for the new bins added
		for(int i=0 ; i < m_bins.size() ; i++ )
		{
			BinSetup bin = (BinSetup)m_bins.get(i);
			if( bin.getPartNumber().trim().length() > 0 && bin.getFG_ProcessStep_ID().equals("-1"))
			{
				str = str + bin.getPartNumber().trim()+"','";
			}
		}
		 
		if( str.length() > 1 )
		{
			result = BinSetupDAO.checkProductTable( str.substring(0,str.length()-2));
		}
		 
		for(int i=0 ; i < m_bins.size() ; i++ )
		{
			BinSetup bin = (BinSetup)m_bins.get(i);
			if( bin.getPartNumber().trim().length() > 0 && !bin.getFG_ProcessStep_ID().equals("-1"))
			{
				str = BinSetupDAO.checkBinsByProcessId( Integer.parseInt(bin.getFG_ProcessStep_ID()) , bin.getPartNumber().trim());
				if( str.length() > 0 )
				{
					if(result.length() > 0 )
					{
						result = result + str + ",";
					}
					else
					{
						result = str ;
					}
				}
			}
		}
	 	if( result.length() > 1 )
	 	{
		 	if( result.substring(result.length()-1).equals(","))
		 	{
				result =  result.substring(0,result.length()-1);
		 	}
	 	}
	 	return result;
	}
	
}